package timing.ukulele.auth.security.user;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.StringUtils;
import timing.ukulele.common.data.ResponseCode;
import timing.ukulele.common.data.ResponseData;
import timing.ukulele.common.dictionary.LoginTypeEnum;
import timing.ukulele.common.dictionary.ThirdPartyTypeEnum;
import timing.ukulele.data.third.view.common.SysThirdPartyUserVO;
import timing.ukulele.data.portal.view.UserVO;
import java.util.*;

@Slf4j
public class TimingUserDetailService implements UserDetailsService {
    private final UnionUserDetailService unionUserDetailService;

    public TimingUserDetailService(UnionUserDetailService unionUserDetailService) {
        this.unionUserDetailService = unionUserDetailService;
    }

    /**
     * 根据用户名获取用户信息
     *
     * @param username 用户名
     * @return UserDetails
     * @throws UsernameNotFoundException 用户未找到
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 账号密码登陆调用FeignClient根据用户名查询用户
        ResponseData<UserVO> baseUserResponseData = this.unionUserDetailService.getUserService().getUserByPhoneOrName(username);
        if (baseUserResponseData.getData() == null || !ResponseCode.SUCCESS.getCode().equals(baseUserResponseData.getCode())) {
            log.error("找不到该用户，用户名：" + username);
            throw new UsernameNotFoundException("找不到该用户，用户名：" + username);
        }
        UserVO baseUser = baseUserResponseData.getData();
        return getUserDetails(baseUser, LoginTypeEnum.PASSWORD.getValue());
    }

    /**
     * 根据手机号查询用户
     *
     * @param mobile 手机号码
     * @return UserDetails
     * @throws UsernameNotFoundException 用户找到
     */
    public UserDetails loadUserByPhone(String mobile) {
        // 手机验证码调用FeignClient根据电话号码查询用户
        ResponseData<UserVO> baseUserResponseData = this.unionUserDetailService.getUserService().getUserByPhone(mobile);
        if (baseUserResponseData.getData() == null || !ResponseCode.SUCCESS.getCode().equals(baseUserResponseData.getCode())) {
            log.error("找不到该用户，手机号码：" + mobile);
            throw new UsernameNotFoundException("找不到该用户，手机号码：" + mobile);
        }
        UserVO user = baseUserResponseData.getData();
        return getUserDetails(user, LoginTypeEnum.PHONE.getValue());
    }

    public boolean hasUserPhone(String mobile){
        ResponseData<UserVO> userRes = this.unionUserDetailService.getUserService().getUserByPhone(mobile);
        if(userRes.getData()==null){
            return false;
        }
        return true;
    }

    public UserDetails loadUserByThirdOpenCode(Integer type, String appId, String code) {
        if (!StringUtils.hasLength(code) || null == type) {
            log.error("传入的第三方数据错误");
            throw new UsernameNotFoundException("传入的第三方数据错误");
        }
        String openId = null;
        // 是否有效的第三方类型
        if(ThirdPartyTypeEnum.hasValue(type)) {
            ResponseData<String> openIdByCode = unionUserDetailService.getThirdCommonFeignFacade().getPlatIdByCode(type, appId, code);
            if (openIdByCode.getData() == null || !ResponseCode.SUCCESS.getCode().equals(openIdByCode.getCode())) {
                throw new UsernameNotFoundException("获取第三方用户信息失败");
            }
            openId = openIdByCode.getData();
        }
        if (!StringUtils.hasLength(openId)) {
            log.error("获取第三方用户信息失败");
            throw new UsernameNotFoundException("获取第三方用户信息失败");
        }
        ResponseData<SysThirdPartyUserVO> userByThirdInfo = unionUserDetailService.getSysThirdPartyUserFeignFacade().getByPlatSourceAndId(type, appId, openId);
        if (userByThirdInfo == null || userByThirdInfo.getData() == null || userByThirdInfo.getData().getId() == null) {
            log.error("找不到该用户，用户名：" + openId);
            throw new UsernameNotFoundException("找不到该用户，用户名：" + openId);
        }
        ResponseData<UserVO> baseUserResponseData = this.unionUserDetailService.getUserService().userInfo(userByThirdInfo.getData().getUserId());
        if (baseUserResponseData.getData() == null || !ResponseCode.SUCCESS.getCode().equals(baseUserResponseData.getCode())) {
            log.error("找不到该用户，用户名：" + userByThirdInfo.getData().getUserId());
            throw new UsernameNotFoundException("找不到该用户，用户名：" + userByThirdInfo.getData().getUserId());
        }
        UserVO user = baseUserResponseData.getData();
        return getUserDetails(user, LoginTypeEnum.THIRD_OPEN.getValue());
    }

    /**
     * 生成用户信息
     *
     * @param baseUser 用户信息
     * @param type     类型
     * @return UserDetails
     */
    private UserDetails getUserDetails(UserVO baseUser, Integer type) {
        List<String> roles;
        if (StringUtils.hasText(baseUser.getLabel())) {
            roles = Collections.singletonList(baseUser.getLabel());
        } else {
            roles = new ArrayList<>(0);
        }

        // 获取用户权限列表
        Set<GrantedAuthority> authorities = convertToAuthorities(roles);
        boolean enabled = baseUser.getDeleted() != null && !baseUser.getDeleted();
        BaseUserDetail baseUserDetail = new BaseUserDetail(type, authorities, true, !baseUser.getDeleted(), true, enabled);
        BeanUtils.copyProperties(baseUser, baseUserDetail);
        return baseUserDetail;
    }

    private Set<GrantedAuthority> convertToAuthorities(List<String> roles) {
        Set<GrantedAuthority> authorities = new HashSet<>();
        roles.forEach(e -> {
            // 存储用户、角色信息到GrantedAuthority，并放到GrantedAuthority列表
            GrantedAuthority authority = new SimpleGrantedAuthority(e.toUpperCase());
            authorities.add(authority);
        });
        return authorities;
    }
}
